package cn.net.isir.controller.miniprogram;

import cn.net.isir.service2.AlipayMinipPayNotifyService;
import cn.net.isir.service2.AlipayMinipPayUnifiedOrderInfoService;
import cn.net.isir.service2.AlipayMinipUserinfoService;
import cn.net.isir.service2.OrderService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import cn.net.isir.common.RequestObject;
import cn.net.isir.common.ResultObject;
import cn.net.isir.common.config.AlipayConfig;
import cn.net.isir.entity.AlipayMinipPayNotify;
import cn.net.isir.entity.AlipayMinipUserinfo;
import cn.net.isir.entity.Order;
import cn.net.isir.utils.DateUtils;
import cn.net.isir.utils.RequestUtils;
import cn.net.isir.utils.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

//import com.sq.entity.Finance;
//import com.sq.entity.FinanceLog;

/**
 * @author liuxubo
 * @filename WxPayController.java
 * @package cn.net.isir.controller.miniprogram
 * @email lxb@isir.net.cn
 * @date 2018/09/18
 * @comment
 * @since 1.7
 */
@RestController("minipAliPayController")
@RequestMapping(value = "/minip/alipaypay")
public class AliPayController {

    private static Logger logger = Logger.getLogger(AliPayController.class);

    @Resource
    private AlipayMinipUserinfoService alipayMinipUserinfoService;
    @Resource
    private AlipayMinipPayUnifiedOrderInfoService alipayMinipPayUnifiedOrderInfoService;
    @Resource
    private AlipayMinipPayNotifyService alipayMinipPayNotifyService;
    @Resource
    private OrderService orderService;

    /**
     * 统一下单接口
     *
     * @param request 请求
     * @param obj     请求参数
     * @return 结果
     */
    @RequestMapping(method = RequestMethod.POST, value = "/order")
    public ResultObject uniformOrder(HttpServletRequest request, @RequestBody RequestObject obj) {
        //声明返回值
        ResultObject ro;
        //声明参数解码后的储存变量
        Map<String, Object> reqParamMap = new HashMap<>();
        //需要检查的字段名
        String[] columns = new String[]{"userid", "shopid", "orderid"};
        //检查失败则返回缺失的字段提示
        if ((ro = RequestUtils.parametersCheck(obj, reqParamMap, columns)).getResult() != 200) {
            return ro;
        }
        String client = String.valueOf(reqParamMap.get("client"));
        String userid = String.valueOf(reqParamMap.get("userid"));
        String shopid = String.valueOf(reqParamMap.get("shopid"));
        String orderid = String.valueOf(reqParamMap.get("orderid"));

        AlipayMinipUserinfo userinfo = new AlipayMinipUserinfo();
        userinfo.setUser_id(userid);
        userinfo = alipayMinipUserinfoService.selectOne(userinfo);
        if (userinfo == null) {
            ro.setResult(500);
            ro.setMessage("未查询到userid对应的用户，请求失败");
            return ro;
        }
        String clientIP = request.getRemoteAddr();

        if ("alipay".equals(client)) {
            ro = alipayMinipPayUnifiedOrderInfoService.uniformOrder(userid, shopid, orderid);
        }

        return ro;
    }

    /**
     * 支付结果通知
     *
     * @param request 请求
     * @return 返回结果
     */

    /**
     * 支付结果通知
     *
     * @param request  请求
     * @param response 相应
     */
    @RequestMapping(value = "/notify")
    @ResponseBody
    public void notify(HttpServletRequest request, HttpServletResponse response) {
        logger.info("支付宝支付成功回调通知");
//        // 获取参数
//        String gmt_payment = request.getParameter("gmt_payment");
//        String notify_id = request.getParameter("notify_id");
//        String seller_email = request.getParameter("seller_email");
//        String notify_type = request.getParameter("notify_type");
//        String sign = request.getParameter("sign");
//        String trade_no = request.getParameter("trade_no");
//        String out_trade_no = request.getParameter("out_trade_no");
//        String gmt_create = request.getParameter("gmt_create");
//        String seller_id = request.getParameter("seller_id");
//        String notify_time = request.getParameter("notify_time");
//        String subject = request.getParameter("subject");
//        String trade_status = request.getParameter("trade_status");
//        String sign_type = request.getParameter("sign_type");
//        // 构建实体类
//        AlipayMinipPayNotify notify = new AlipayMinipPayNotify();
//        notify.setGmt_payment(DateUtils.parse(gmt_payment, "yyyy-MM-dd HH:mm:ss"));
//        notify.setNotify_id(notify_id);
//        notify.setSeller_email(seller_email);
//        notify.setNotify_type(notify_type);
//        notify.setSign(sign);
//        notify.setTrade_no(trade_no);
//        notify.setOut_trade_no(out_trade_no);
//        notify.setGmt_create(DateUtils.parse(gmt_create, "yyyy-MM-dd HH:mm:ss"));
//        notify.setSeller_id(seller_id);
//        notify.setNotify_time(DateUtils.parse(notify_time, "yyyy-MM-dd HH:mm:ss"));
//        notify.setSubject(subject);
//        notify.setTrade_status(trade_status);
//        notify.setSign_type(sign_type);

        PrintWriter out = null;
        try {
            out = response.getWriter();
        } catch (IOException e) {
            e.printStackTrace();
        }

        //获取支付宝POST过来反馈信息
        Map<String, String> params = new HashMap<>();
        Map requestParams = request.getParameterMap();
        for (Object o1 : requestParams.keySet()) {
            String name = (String) o1;
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            //乱码解决，这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
            //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
            params.put(name, valueStr);
        }
        //获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//

        //商户订单号
        String out_trade_no = null;
        //支付宝交易号
        String trade_no = null;
        //交易状态
        String trade_status = null;
        //商户订单号
        out_trade_no = request.getParameter("out_trade_no");
        //支付宝交易号
        trade_no = request.getParameter("trade_no");
        //交易状态
        trade_status = request.getParameter("trade_status");

        //获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//
        //计算得出通知验证结果
        //boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type)
        boolean verify_result = false;
        try {
            logger.info(params);
            verify_result = AlipaySignature.rsaCheckV1(params,
                    AlipayConfig.getAlipay_public_key_pay(),
                    StandardCharsets.UTF_8.name(),
                    "RSA2");
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        logger.info("验签结果：" + verify_result);

        if (verify_result) {//验证成功
            //////////////////////////////////////////////////////////////////////////////////////////
            //请在这里加上商户的业务逻辑程序代码

            AlipayMinipPayNotify notify = new AlipayMinipPayNotify();
            try {
                //保存通知日志
                notify.setOrderInfoId(params.get("orderInfoId"));
                notify.setNotify_time(DateUtils.parse(params.get("notify_time"), "yyyy-MM-dd HH:mm:ss"));
                notify.setNotify_type(params.get("notify_type"));
                notify.setNotify_id(params.get("notify_id"));
                notify.setSign_type(params.get("sign_type"));
                notify.setSign(params.get("sign"));
                notify.setTrade_no(params.get("trade_no"));
                notify.setApp_id(params.get("app_id"));
                notify.setOut_trade_no(params.get("out_trade_no"));
                notify.setOut_biz_no(params.get("out_biz_no"));
                notify.setBuyer_id(params.get("buyer_id"));
                notify.setBuyer_logon_id(params.get("buyer_logon_id"));
                notify.setSeller_id(params.get("seller_id"));
                notify.setSeller_email(params.get("seller_email"));
                notify.setTrade_status(params.get("trade_status"));
                String total_amount = params.get("total_amount");
                notify.setTotal_amount(StringUtils.isNotBlank(total_amount) ? new BigDecimal(total_amount) : null);
                String receipt_amount = params.get("receipt_amount");
                notify.setReceipt_amount(StringUtils.isNotBlank(receipt_amount) ? new BigDecimal(receipt_amount) : null);
                String invoice_amount = params.get("invoice_amount");
                notify.setInvoice_amount(StringUtils.isNotBlank(invoice_amount) ? new BigDecimal(invoice_amount) : null);
                String buyer_pay_amount = params.get("buyer_pay_amount");
                notify.setBuyer_pay_amount(StringUtils.isNotBlank(buyer_pay_amount) ? new BigDecimal(buyer_pay_amount) : null);
                String point_amount = params.get("point_amount");
                notify.setPoint_amount(StringUtils.isNotBlank(point_amount) ? new BigDecimal(point_amount) : null);
                String refund_fee = params.get("refund_fee");
                notify.setRefund_fee(StringUtils.isNotBlank(refund_fee) ? new BigDecimal(refund_fee) : null);
                String send_back_fee = params.get("send_back_fee");
                notify.setSend_back_fee(StringUtils.isNotBlank(send_back_fee) ? new BigDecimal(send_back_fee) : null);
                notify.setSubject(params.get("subject"));
                notify.setBody(params.get("body"));
                notify.setGmt_create(DateUtils.parse(params.get("gmt_create"), "yyyy-MM-dd HH:mm:ss"));
                notify.setGmt_payment(DateUtils.parse(params.get("gmt_payment"), "yyyy-MM-dd HH:mm:ss"));
                notify.setGmt_refund(DateUtils.parse(params.get("gmt_refund"), "yyyy-MM-dd HH:mm:ss"));
                notify.setGmt_close(DateUtils.parse(params.get("gmt_close"), "yyyy-MM-dd HH:mm:ss"));
                notify.setFund_bill_list(params.get("fund_bill_list"));
                logger.info(notify.toString());
                alipayMinipPayNotifyService.insert(notify);
            } catch (Exception ex) {
                ex.printStackTrace();
                logger.info(notify);
                logger.error(ex);
            }


            Order order = new Order();
            order.setNo(out_trade_no);
            order = orderService.selectOne(order);
            logger.info(order);
            //支付金额
            String total_fee = params.get("total_amount");
            BigDecimal notify_total_fee = StringUtils.isNotBlank(total_fee) ? new BigDecimal(total_fee) : null;
            //支付人
            String order_user = order.getOrderUser();
            //支付方式
            String payment = null;
            try {
                String paymentStr = params.get("fund_bill_list");
                JSONArray jsonArray = JSONArray.parseArray(paymentStr);
                Object o = jsonArray.get(0);
                JSONObject jsonObject = JSONObject.parseObject(JSON.toJSONString(o));
                payment = String.valueOf(jsonObject.get("fundChannel"));
            } catch (Exception ex) {
                ex.printStackTrace();
                logger.info("支付宝--通知--支付方式为空");
            }

            //——请根据您的业务逻辑来编写程序（以下代码仅作参考）——

            if ("TRADE_FINISHED".equals(trade_status)) {
                //判断该笔订单是否在商户网站中已经做过处理

                if (order.getIsPaid() != 1) {
                    //如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                    //请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的
                    if (order.getFinalTotal().compareTo(notify_total_fee) == 0) {
//                        orderService.paidOrderHandle(out_trade_no, order_user, payment, "alipay");
                        logger.info("支付宝--通知---退款协议发生");
                        logger.info(params);
                    }
                }


                //注意：
                //如果签约的是可退款协议，退款日期超过可退款期限后（如三个月可退款），支付宝系统发送该交易状态通知
                //如果没有签约可退款协议，那么付款完成后，支付宝系统发送该交易状态通知。
            }
            if ("TRADE_SUCCESS".equals(trade_status)) {
                //判断该笔订单是否在商户网站中已经做过处理
                if (order.getIsPaid() != 1) {
                    //如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                    if (order.getFinalTotal().compareTo(notify_total_fee) == 0) {
                        //fund_bill_list---支付金额信息----[{"amount":"15.00","fundChannel":"ALIPAYACCOUNT"}]

                        //支付渠道代码------------支付渠道
                        //COUPON------------支付宝红包
                        //ALIPAYACCOUNT------------支付宝余额
                        //POINT------------集分宝
                        //DISCOUNT------------折扣券
                        //PCARD------------预付卡
                        //FINANCEACCOUNT------------余额宝
                        //MCARD------------商家储值卡
                        //MDISCOUNT------------商户优惠券
                        //MCOUPON------------商户红包
                        //PCREDIT------------蚂蚁花呗
                        orderService.paidOrderHandle(out_trade_no, order_user, payment, "alipay");
                    }
                    //请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的
                }

                //注意：
                //如果签约的是可退款协议，那么付款完成后，支付宝系统发送该交易状态通知。
            }

            //——请根据您的业务逻辑来编写程序（以上代码仅作参考）——
            if (out != null) {
                out.println("success");    //请不要修改或删除
                logger.info("success");
            }

            //////////////////////////////////////////////////////////////////////////////////////////
        } else {//验证失败
            if (out != null) {
                out.println("fail");
            }
        }
        if (out != null) {
            out.flush();
            out.close();
        }
    }
}
